package com.gridmobi.xrtb.handler;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.gridmobi.xrtb.common.ExecutorPool;
import com.gridmobi.xrtb.domain.adn.OsE;
import com.gridmobi.xrtb.model.SspE;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.stream.Stream;

//@Component
public class DeviceIdHandler {

    private static final Logger logger = LoggerFactory.getLogger(DeviceIdHandler.class);


    public static final Map<String, List<String>> GEO_FILES = Maps.newHashMap();
    public static Map<String, ArrayBlockingQueue<String>> GEO_OS_QUE = Maps.newHashMap();
    @Value("${devidrootpath}")
    private String devidrootpath;
    @Value("${devidgeos}")
    private String devidgeos = "PHL,VNM,IDN,THA";

    @Value("${client.script}")
    private int script;

    public static String takeDevid(String geo3, String osKeyLow) {
        try {
            String key = geo3 + osKeyLow;
            if (GEO_OS_QUE.containsKey(key)) {
                return GEO_OS_QUE.get(key).take();
            } else {
                return null;

            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static DeviceInfo getDevid(String deviceid) {
        DeviceInfo deviceInfo = new DeviceInfo();


        if (deviceid.indexOf("@") > 0) {

            String[] devs = deviceid.split("@");
            deviceInfo.setDevid(devs[5]);
            deviceInfo.setSsp(SspE.getV(devs[0]));
            deviceInfo.setOs(devs[2]);
            deviceInfo.setAppid(devs[3]);
            deviceInfo.setGeo(devs[1]);
            deviceInfo.setPub(devs[4]);

            if (devs.length >= 7) {
                deviceInfo.setMake(devs[6]);
            }
            if (devs.length >= 8) {
                deviceInfo.setUa(devs[7]);
            }
            if (devs.length >= 9) {
                deviceInfo.setLang(devs[8]);
            }
            if (devs.length >= 10) {
                deviceInfo.setOsv(devs[9]);
            }
            if (devs.length >= 11) {
                deviceInfo.setIp(devs[10]);
            }
            deviceInfo.setLongdata(true);
        } else {
            deviceInfo.setLongdata(false);
            deviceInfo.setDevid(deviceid);
        }
        return deviceInfo;
    }

    @PostConstruct
    public void start() {
        if (script == 1) {

            System.out.println(devidgeos);
            System.out.println(devidrootpath);
            Stream.of(devidgeos.split(",")).forEach(geo3 -> {
                if (!GEO_OS_QUE.containsKey(geo3 + OsE.iOS.key)) {

                    GEO_OS_QUE.put(geo3 + OsE.iOS.key, new ArrayBlockingQueue<String>(20000));
                }
                if (!GEO_OS_QUE.containsKey(geo3 + OsE.Android.key)) {
                    GEO_OS_QUE.put(geo3 + OsE.Android.key, new ArrayBlockingQueue<String>(20000));
                }
            });

            getGeoOsFiles();
            Stream.of(devidgeos.split(",")).forEach(geo3 -> {
                loadDevid(geo3, OsE.Android.key);
                loadDevid(geo3, OsE.iOS.key);
            });
        }
    }

    public void loadDevid(String geo3, String os) {


        String key3 = geo3 + os;

        if (!GEO_FILES.containsKey(key3)) {
            return;
        }
        ExecutorPool.getExecutor().execute(() -> {

            ArrayBlockingQueue q = GEO_OS_QUE.get(key3);

            List<String> files = GEO_FILES.get(key3);
            while (true) {
                files.forEach(p -> {
                    try {
                        File file = new File(p);
                        if (file.isDirectory()) {
                            return;
                        }
                        FileReader fileReader = new FileReader(file);

                        BufferedReader bf = new BufferedReader(fileReader);
                        String str;
                        while (org.apache.commons.lang3.StringUtils.isNotBlank(str = bf.readLine())) {
                            try {
                                q.put(str);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        bf.close();
                        fileReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                });
            }

        });
    }

    public void getGeoOsFiles() {

        try {
            String rootpath = devidrootpath;
            List<String> days = Lists.newArrayList();

            for (int i = 0; i <= 3; i++) {
                days.add(LocalDateTime.now(ZoneOffset.UTC).plusDays((0 - i)).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
            }
            java.nio.file.Files.walkFileTree(new File(rootpath + "/").toPath(), new SimpleFileVisitor<Path>() {

                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    String path = file.toString();
                    String os = OsE.iOS.key;
                    int i = path.indexOf("ios.device");
                    if (i < 0) {
                        os = OsE.Android.key;
                        i = path.indexOf("android.device");
                    }
                    if (i < 4) {
                        logger.warn("errorpath:" + path);
                    } else {
                        String geo = path.substring(i - 4, i - 1);
                        if (devidgeos.toLowerCase().indexOf(geo) >= 0) {

                            if (i > 0 && !StringUtils.isEmpty(geo) && !StringUtils.isEmpty(os)) {
                                String key = geo.toUpperCase() + os;
                                if (!GEO_FILES.containsKey(key)) {
                                    GEO_FILES.put(key, Lists.newArrayList());
                                }

                                days.forEach(day -> {
                                    if (path.indexOf(day) > 0) {
                                        GEO_FILES.get(key).add(path);
                                    }
                                });
                            }
                        }
                    }
                    return super.visitFile(file, attrs);
                }

                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    return FileVisitResult.CONTINUE;
                }

            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        GEO_FILES.forEach((k, v) -> {

            Collections.shuffle(v);
            GEO_FILES.put(k, v);
        });

        GEO_FILES.forEach((k, v) -> {
            v.stream().forEach(n -> {
                logger.warn("+++++++++++IMPORTINFO:FILE=" + k + ":" + n);

            });
        });

    }


}
